package dryven.util.json.dryvenjson;

import java.io.IOException;

import dryven.model.di.DependencyService;
import dryven.model.di.LocalThreadStorage;
import dryven.util.json.JsonEncoder;

public class JSONCompositeEncoder implements JsonEncoder {
	private Iterable<JSONTypeEncoder> _encoders;
	private FieldPolicy _fieldPolicy;
	private boolean _avoidNull;
	
	public JSONCompositeEncoder(FieldPolicy fieldPolicy, Iterable<JSONTypeEncoder> encoders, boolean avoidNull) {
		super();
		_fieldPolicy = fieldPolicy;
		_encoders = encoders;
		_avoidNull = avoidNull;
	}
	
	@Override
	public void encodeRootValue(Object value, LocalThreadStorage diStorage, Appendable dest) throws IOException {
		encodeValue(value,diStorage,dest,false);
	}
	
	public void encodePropertyValue(Object value, LocalThreadStorage diStorage, Appendable dest) throws IOException {
		encodeValue(value,diStorage,dest,true);
	}

	protected void encodeValue(Object value, LocalThreadStorage diStorage, Appendable dest, boolean isProperty) throws IOException {
		if(value==null) {
			encodeNull(String.class, dest, isProperty);
		}
		else {
			for(JSONTypeEncoder enc:_encoders) {
				if(enc.isApplicableForType(value.getClass())) {
					enc.encodeValue(value, this, _fieldPolicy, diStorage, dest);
					return;
				}
			}
			throw new RuntimeException("Could not find an encoding method for the given value");
		}
	}
	
	public void encodeNull(Class<?> type, Appendable dest, boolean isProperty) throws IOException {
		if(type==String.class && _avoidNull && isProperty) {
			dest.append("\"\"");
		} else {
			dest.append("null");
		}
	}

	public FieldPolicy getFieldPolicy() {
		return _fieldPolicy;
	}
}
